package ofpof.service;

import java.util.Date;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import ofpof.domain.RemembermeToken;
import ofpof.domain.Session;
import ofpof.domain.User;
import ofpof.domain.dao.RemembermeTokenDao;
import ofpof.domain.dao.UserDao;
import ofpof.web.form.LoginForm;

import org.bson.types.ObjectId;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class SecurityService implements DisposableBean {
	private static final int TWOWEEKS = 60*60*24*15;
	private static final String OFPOFTOKENCOOKIE = "ofpoftoken";
	private static final ThreadLocal<User> USER = new ThreadLocal<User>();

	@Autowired
	private UserDao userDao;

	@Autowired
	private SessionService sessionService;

	@Autowired
	private RemembermeTokenDao remembermeTokenDao;
	
	@Autowired
	private CookieHelper cookieHelper;
	
	public boolean isLoggedIn() {
		return USER.get()!= null;
	}

	public User getCurrentUser() {
		return USER.get();
	}
	
	public void clearThreadLocal() {
		USER.remove();
	}

	public boolean loginUser(LoginForm loginForm, HttpServletResponse response) {
		String email = loginForm.getUser().getEmail();
		String password = loginForm.getUser().getPassword();
		User foundUser = userDao.findByEmailAndPassword(email, password);
		
		if (foundUser == null) {
			return false;
		}
		
		if (!foundUser.isActive()) {
			return false;
		}

		initSessionForUser(response, foundUser);

		if (loginForm.isRememberMe()) {
			createRememberMeToken(foundUser, response);
		}

		return true;
	}

	

	public void confirmUser(User user, HttpServletResponse response) {
		user.setActive(true);
		userDao.update(user);
		initSessionForUser(response, user);
	}

	public void logout(HttpServletRequest request, HttpServletResponse response) {
		Cookie sessionCookie = cookieHelper.getCookie(request, SessionService.OFPOFID);
		if (sessionCookie == null) {
			return;
		}
		cookieHelper.removeCookie(response,sessionCookie);
		
		Cookie rememberMeCookie = cookieHelper.getCookie(request, OFPOFTOKENCOOKIE);
		if (rememberMeCookie != null) {
			cookieHelper.removeCookie(response,rememberMeCookie);
		}
		
		sessionService.deleteSessionById(sessionCookie.getValue());
		User user = USER.get();
		remembermeTokenDao.deleteTokensOfUser(user);
		USER.remove();
	}

	public void tryLoginWithCookies(HttpServletRequest request,HttpServletResponse response) {
		boolean loggedIn = tryLoginWithSessionCookie(request,response);
		
		if (!loggedIn) {
			tryLoginWithRemembermeCookie(request,response);
		}
	}
	
	
	private boolean tryLoginWithRemembermeCookie(HttpServletRequest request,HttpServletResponse response) {
		Cookie remembermeCookie = cookieHelper.getCookie(request, SecurityService.OFPOFTOKENCOOKIE);
		if (remembermeCookie != null) {
			String tokenValue = remembermeCookie.getValue();
			RemembermeToken tokenFromCookie = RemembermeToken.fromString(tokenValue);
			RemembermeToken tokenFromDb = remembermeTokenDao.findByToken(tokenFromCookie);
			if (tokenFromDb == null) {
				return false;
			}
			User foundUser = userDao.findByEmail(tokenFromDb.getEmail());
			if (foundUser == null) {
				return false;
			}

			initSessionForUser(response, foundUser);
			
			tokenFromDb.setToken(new ObjectId().toString());
			tokenFromDb.setLastLogin(new Date());
			cookieHelper.createPersistentCookie(response,OFPOFTOKENCOOKIE, tokenFromDb.asCookieString(), TWOWEEKS);
			remembermeTokenDao.update(tokenFromDb);
			return true;
		}
		
		return false;
	}
	
	private void createRememberMeToken(User foundUser, HttpServletResponse response) {
		RemembermeToken token = new RemembermeToken();
		token.setId(new ObjectId());
		token.setLastLogin(new Date());
		token.setToken(new ObjectId().toString());
		token.setEmail(foundUser.getEmail());
		remembermeTokenDao.create(token);
		cookieHelper.createPersistentCookie(response,OFPOFTOKENCOOKIE, token.asCookieString(), TWOWEEKS);
	}

	private void initSessionForUser(HttpServletResponse response,User user) {
		sessionService.createSessionFor(user, response);
		USER.set(user);
	}

	private boolean tryLoginWithSessionCookie(HttpServletRequest request,HttpServletResponse response) {
		Cookie sessionCookie = cookieHelper.getCookie(request, SessionService.OFPOFID);
		if (sessionCookie != null) {
			Session foundSession = sessionService.updateSessionIfExists(sessionCookie.getValue());
			if (foundSession != null) {
				User user = userDao.findById(foundSession.getUser().getId());
				USER.set(user);
				return true;
			}
			
			cookieHelper.removeCookie(response, sessionCookie);
		}
		return false;
	}
	
	@Override
	public void destroy() throws Exception {
		clearThreadLocal();
	}

	public void sendUserEmail(String email) {
		
	}

}
